﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ProlicySocketServer
{

    using System.Net.Sockets;
    using System.Threading;
    using System.Net;


    /// <summary>
    /// 实现 Silverlight Socket 策略文件发送的实体类
    /// </summary>
    /// <remarks>
    ///         /// 事件代码
    ///         /// <param name="sender"></param>
    ///         /// <param name="e"></param>
    ///         void procliySocketEntity_MessageChanged(object sender, ProcliySocketOutMessageEventArgs e)
    ///         {
    ///             ///线程调用UI
    ///             Dispatcher.BeginInvoke(
    ///                 (System.Threading.ThreadStart)delegate()
    ///                 {
    ///                     label1.Content += e.OutMessage+"\r\n";
    ///                 },
    ///                  System.Windows.Threading.DispatcherPriority.Normal, null);
    ///         }
    ///         /// 运行
    ///         void Run()
    ///         {
    ///             var procliySocketEntity = new ProcliySocketEntity();
    ///             procliySocketEntity.MessageChanged += new ProcliySocketOutMessage(procliySocketEntity_MessageChanged);
    ///             procliySocketEntity.StartSocketServer();
    ///         }
    ///         /// 调用运行代码
    ///         /// <param name="sender"></param>
    ///         /// <param name="e"></param>
    ///         private void button1_Click(object sender, RoutedEventArgs e)
    ///         {
    ///             System.Threading.Thread Thr = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
    ///             Thr.Start();
    ///         }
    /// </remarks>
    public class ProcliySocketEntity
    {




        #region 定义变量

        /// <summary>
        /// 初始化 TcpListener 对像
        /// </summary>
        TcpListener _Listener = null;

        /// <summary>
        /// 初始化 Tcp 客户端对像
        /// </summary>
        TcpClient _Client = null;

        /// <summary>
        /// 定义 一个TCP联接对像
        /// 表示一个线程同步事件
        /// ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/fxref_mscorlib/html/de200b0d-1444-e592-5f3e-e6780b680857.htm
        /// </summary>
        ManualResetEvent _TcpClientConnectioned = new ManualResetEvent(false);

        /// <summary>
        /// 代理的字符串
        /// </summary>
        const string PolicyRequestString = "<policy-file-request/>";

        /// <summary>
        /// 初始化已经接收的数据长度
        /// </summary>
        int ReceivedLength = 0;

        /// <summary>
        /// 初始化代理 数据
        /// </summary>
        byte[] _Policy = null;


        /// <summary>
        /// 接收的数据
        /// </summary>
        byte[] _ReceiveBuffer = null;
        #endregion


        #region 定义公共的属性
        /// <summary>
        /// 默认的监听端口
        /// 默认 943 端口
        /// </summary>
        private int listenerPort = 943;

        /// <summary>
        /// 默认的监听端口
        /// 默认 943 端口
        /// </summary>
        public int ListenerPort
        {
            get { return listenerPort; }
            set { listenerPort = value; }
        }
        #endregion


        #region 私有方法

        /// <summary>
        /// 初始化数据
        /// </summary>
        private void InitlalizeData()
        {
            ///从app.Config 文件中找到 AppSettings 节点 PolicyFilePath  的键中得到路径
            string policyFile = System.Configuration.ConfigurationManager.AppSettings["PolicyFilePath"];

            //将文件文件读入进来并转换成为 字节数组
            _Policy = System.IO.File.ReadAllBytes(policyFile);

            ///初始化 接收的字节长度
            _ReceiveBuffer = new byte[PolicyRequestString.Length];


        }


        /// <summary>
        /// 注册事件 
        /// </summary>
        /// <param name="str"> 要传入的字符串</param>
        private void RegMessageChanged(string str)
        {
            if (MessageChanged != null)
            {
                MessageChanged(this, new ProcliySocketOutMessageEventArgs(str));
            }
        }

        /// <summary>
        /// 监听后开始接收数据
        /// </summary>
        /// <param name="ar"></param>
        private void OnBeginAccept(IAsyncResult ar)
        {
            try
            {
                ///异步接受传入的连接尝试，并创建新的 TcpClient 来处理远程主机通信。
                _Client = _Listener.EndAcceptTcpClient(ar);
                _Client.Client.BeginReceive(_ReceiveBuffer, 0, PolicyRequestString.Length,
                    SocketFlags.None, new AsyncCallback(OnReceiveComplete), null);
            }
            catch (ObjectDisposedException SocketEx)
            {
                RegMessageChanged(SocketEx.ToString());
            }
        }


        /// <summary>
        /// 当异步接收完成
        /// </summary>
        /// <param name="ar"></param>
        private void OnReceiveComplete(IAsyncResult ar)
        {
            ///结束挂起的异步读取。
            ReceivedLength += _Client.Client.EndReceive(ar);
            
            //看看是不是要再次收数据
            //如果长度不够 再进行接收数据
             if (ReceivedLength < PolicyRequestString.Length)
            {
                _Client.Client.BeginReceive(_ReceiveBuffer, ReceivedLength,
                    PolicyRequestString.Length - ReceivedLength,
                      SocketFlags.None, new AsyncCallback(OnReceiveComplete), null
                      );
                return;
            }


            //当长度够了
            //得到收到的字符串
             string request = System.Text.Encoding.UTF8.GetString(_ReceiveBuffer, 0, ReceivedLength);

            //进行字符串比较
             if (StringComparer.InvariantCultureIgnoreCase.Compare(request, PolicyRequestString) != 0)
             {
                 ///关闭客户端
                 _Client.Client.Close();
                 return;
             }

            ///发送指定的字符串
             _Client.Client.BeginSend(_Policy, 0, _Policy.Length, SocketFlags.None, new AsyncCallback(onSendComplete), null);



            //将联接还原
             ReceivedLength = 0;
            ///总是等待线程
             _TcpClientConnectioned.Set();

        }

         /// <summary>
        /// 当异步发送完成
        /// </summary>
        private void onSendComplete(IAsyncResult ar)
        {
            try
            {
                _Client.Client.Close();
            }
            catch (Exception ex)
            {
                RegMessageChanged(ex.ToString());
            }
            finally
            {
                try
                {
                    //关闭联接
                    _Client.Client.Close();
                }
                catch { 
                
                }
            }
        }

        #endregion

        #region 公共方法

        public void StartSocketServer()
        {
            try
            {
                ///初始化数据
                InitlalizeData();

                try
                {
                    //创建一个监听
                    _Listener = new TcpListener(System.Net.IPAddress.Any, ListenerPort);

                    ///开始监听
                    _Listener.Start();
                }
                catch (SocketException ex)
                {
                    try
                    {
                        _Listener.Stop();
                    }
                    catch (Exception exx)
                    {

                        RegMessageChanged(exx.ToString());
                    }

                    RegMessageChanged(ex.ToString());
                    return;
                }
                RegMessageChanged("开始监听 端口:" + ListenerPort);

                while (true)
                {
                    //将事件状态设置为非终止状态，导致线程阻止。
                    _TcpClientConnectioned.Reset();
                    RegMessageChanged("等待客户端联接....");
                    //开始进行 Socket 客户端
                    _Listener.BeginAcceptTcpClient(new AsyncCallback(OnBeginAccept), null);

                    //阻止当前线程，直到当前 WaitHandle 收到信号。 （ WaitHa继承自ndle。）
                    _TcpClientConnectioned.WaitOne();
                }

            }
            catch
            {

            }

        }


        /// <summary>
        /// 停止 Socket
        /// </summary>
        public void StopSocketServer()
        {
            try
            {
                _Listener.Stop();
                RegMessageChanged(" 端口:" + ListenerPort + "监听已停止");
            }
            catch (Exception ex)
            {

                RegMessageChanged(ex.ToString());
            }

        }
        #endregion

        #region 事件

        /// <summary>
        /// 定义一个事件
        /// </summary>
        public event ProcliySocketOutMessage MessageChanged;

        #endregion
    }


    #region 定义 委托 与事件
    /// <summary>
    /// 输出信息的 委托
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void ProcliySocketOutMessage(object sender, ProcliySocketOutMessageEventArgs e);

    /// <summary>
    /// Socket输出事件
    /// </summary>
    public class ProcliySocketOutMessageEventArgs : EventArgs
    {

        public ProcliySocketOutMessageEventArgs(string outMessage)
        {
            this.outMessage = outMessage;
            }
        /// <summary>
        /// 输出信息
        /// </summary>
        private string outMessage = "";

        /// <summary>
        /// 输出信息
        /// </summary>
        public string OutMessage
        {
            get { return outMessage; }
        }
    }    
    #endregion

}
